From 563fae70e8eb4f5f8e18ccfd1907f34a51c7064e Mon Sep 17 00:00:00 2001 From: "tdeegan@york.uk.xensource.com" Date: Thu, 17 Aug 2006 16:05:51 +0100 Subject: [PATCH] Fix handling of PS bit in 64-bit pagetables Signed-off-by: Tim Deegan --- xen/arch/x86/shadow2-common.c | 8 +++--- xen/arch/x86/shadow2.c | 41 +++++++++++++++++++++------ xen/include/asm-x86/shadow2-private.h | 19 ------------- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/xen/arch/x86/shadow2-common.c b/xen/arch/x86/shadow2-common.c index eab6361c3d..4b3b49e333 100644 --- a/xen/arch/x86/shadow2-common.c +++ b/xen/arch/x86/shadow2-common.c @@ -2165,9 +2165,6 @@ void sh2_remove_shadows(struct vcpu *v, mfn_t gmfn, int all) 0 /* unused */ }; - SHADOW2_PRINTK("d=%d, v=%d, gmfn=%05lx\n", - v->domain->domain_id, v->vcpu_id, mfn_x(gmfn)); - ASSERT(shadow2_lock_is_acquired(v->domain)); pg = mfn_to_page(gmfn); @@ -2176,6 +2173,9 @@ void sh2_remove_shadows(struct vcpu *v, mfn_t gmfn, int all) if ( (pg->count_info & PGC_page_table) == 0 ) return; + SHADOW2_PRINTK("d=%d, v=%d, gmfn=%05lx\n", + v->domain->domain_id, v->vcpu_id, mfn_x(gmfn)); + /* Search for this shadow in all appropriate shadows */ perfc_incrc(shadow2_unshadow); sh_flags = pg->shadow2_flags; @@ -2843,7 +2843,7 @@ sh2_p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn) v = d->vcpu[0]; - SHADOW2_PRINTK("removing gfn=%#lx mfn=%#lx\n", gfn, mfn); + SHADOW2_DEBUG(P2M, "removing gfn=%#lx mfn=%#lx\n", gfn, mfn); ASSERT(mfn_x(sh2_gfn_to_mfn(d, gfn)) == mfn); //ASSERT(sh2_mfn_to_gfn(d, mfn) == gfn); diff --git a/xen/arch/x86/shadow2.c b/xen/arch/x86/shadow2.c index 9d845cb797..b75c7062bd 100644 --- a/xen/arch/x86/shadow2.c +++ b/xen/arch/x86/shadow2.c @@ -234,6 +234,28 @@ delete_shadow2_status(struct vcpu *v, mfn_t gmfn, u32 shadow_type, mfn_t smfn) put_page(mfn_to_page(gmfn)); } +/**************************************************************************/ +/* CPU feature support querying */ + +static inline int +guest_supports_superpages(struct vcpu *v) +{ + /* The _PAGE_PSE bit must be honoured in HVM guests, whenever + * CR4.PSE is set or the guest is in PAE or long mode */ + return (hvm_guest(v) && (GUEST_PAGING_LEVELS != 2 + || (hvm_get_guest_ctrl_reg(v, 4) & X86_CR4_PSE))); +} + +static inline int +guest_supports_nx(struct vcpu *v) +{ + if ( !hvm_guest(v) ) + return cpu_has_nx; + + // XXX - fix this! + return 1; +} + /**************************************************************************/ /* Functions for walking the guest page tables */ @@ -482,9 +504,11 @@ static u32 guest_set_ad_bits(struct vcpu *v, if ( unlikely(GUEST_PAGING_LEVELS == 3 && level == 3) ) return flags; - /* Need the D bit as well for writes, in l1es and PSE l2es. */ + /* Need the D bit as well for writes, in l1es and 32bit/PAE PSE l2es. */ if ( ft == ft_demand_write - && (level == 1 || (level == 2 && (flags & _PAGE_PSE))) ) + && (level == 1 || + (level == 2 && GUEST_PAGING_LEVELS < 4 + && (flags & _PAGE_PSE) && guest_supports_superpages(v))) ) { if ( (flags & (_PAGE_DIRTY | _PAGE_ACCESSED)) == (_PAGE_DIRTY | _PAGE_ACCESSED) ) @@ -709,7 +733,6 @@ sh2_propagate_flags(struct vcpu *v, mfn_t target_mfn, struct domain *d = v->domain; u32 pass_thru_flags; u32 sflags; - int lowest_level_guest_mapping; // XXX -- might want to think about PAT support for HVM guests... @@ -782,10 +805,6 @@ sh2_propagate_flags(struct vcpu *v, mfn_t target_mfn, if ( (level > 1) && !((SHADOW_PAGING_LEVELS == 3) && (level == 3)) ) sflags |= _PAGE_ACCESSED | _PAGE_DIRTY; - lowest_level_guest_mapping = - ((level == 1) || - ((level == 2) && guest_supports_superpages(v) && - (gflags & _PAGE_PSE))); // Set the A and D bits in the guest entry, if we need to. if ( guest_entry_ptr && (ft & FETCH_TYPE_DEMAND) ) @@ -798,8 +817,12 @@ sh2_propagate_flags(struct vcpu *v, mfn_t target_mfn, !(gflags & _PAGE_ACCESSED)) ) sflags &= ~_PAGE_PRESENT; - if ( unlikely(lowest_level_guest_mapping && - !(gflags & _PAGE_DIRTY)) ) + /* D bits exist in l1es, and 32bit/PAE PSE l2es, but not 64bit PSE l2es */ + if ( unlikely( ((level == 1) + || ((level == 2) && (GUEST_PAGING_LEVELS < 4) + && guest_supports_superpages(v) && + (gflags & _PAGE_PSE))) + && !(gflags & _PAGE_DIRTY)) ) sflags &= ~_PAGE_RW; // MMIO caching diff --git a/xen/include/asm-x86/shadow2-private.h b/xen/include/asm-x86/shadow2-private.h index 7b2ac57572..284e06d80e 100644 --- a/xen/include/asm-x86/shadow2-private.h +++ b/xen/include/asm-x86/shadow2-private.h @@ -532,25 +532,6 @@ static inline void sh2_unpin(struct vcpu *v, mfn_t smfn) } } -/**************************************************************************/ -/* CPU feature support querying */ - -static inline int -guest_supports_superpages(struct vcpu *v) -{ - return hvm_guest(v) && (hvm_get_guest_ctrl_reg(v, 4) & X86_CR4_PSE); -} - -static inline int -guest_supports_nx(struct vcpu *v) -{ - if ( !hvm_guest(v) ) - return cpu_has_nx; - - // XXX - fix this! - return 1; -} - /**************************************************************************/ /* Guest physmap (p2m) support */ -- 2.30.2